#include "string_util/string_util.h"
#include "stun_protocol/stun_protocol_attr.h"
#include "stun_protocol/stun_protocol_msg.h"

#include <cstdint>
#include <cstdio>
#include <cstring>
#include <gtest/gtest.h>
#include <memory>
#include <string>

TEST(StunMsg, Test)
{
    StunMsg msg;
    msg.MsgMagicCookie(0x2112a442);
    uint8_t transacton[StunMsg::TRANSACTION_LENGTH] = {};
    StunMsg::CreateTransactionID(transacton);
    msg.TransactionId(transacton);
    msg.MsgType(0x0001);
    uint8_t data[100] = {};
    int     length    = msg.Compose(data, sizeof(data));
    printf("result : %d.\n", length);
    std::string hex_result;
    StringUtil::DataToHexStr(data, length, hex_result);
    printf("result:%s.\n", hex_result.c_str());
    // compose:000100002112a4422cf2f07f8106ba0b8bab67e7.
    // compose:000100002112a4424331c3daf23ae89d15b5c3b8.
    // raw    :000100002112a442cda344c6ffa066d311b63dac
}

TEST(StunMsg, TestComposeAttr)
{
    StunMsg msg;
    msg.MsgMagicCookie(0x2112a442);
    uint8_t transacton[StunMsg::TRANSACTION_LENGTH] = {};
    StunMsg::CreateTransactionID(transacton);
    msg.TransactionId(transacton);
    msg.MsgType(0x0001);
    auto attr = std::make_shared<StunUserNameAttr>();
    attr->UserName("123456789");
    msg.AddAttr(attr);
    uint8_t data[100] = {};
    int     length    = msg.Compose(data, sizeof(data));
    printf("result : %d.\n", length);
    std::string hex_result;
    StringUtil::DataToHexStr(data, length, hex_result);
    printf("result:%s.\n", hex_result.c_str());
}

TEST(AddressMap, ComposeTest)
{
    StunMappedAddressAttr attr = {};
    attr.AddressInfo(0x01, 8032, "124.79.63.132");
    uint8_t data[100] = {};
    int     length    = attr.ComposeAttrToBuffer(data, sizeof(data));
    printf("result : %d.\n", length);
    printf("ip:%s port:%d.\n", attr.HostIP().c_str(), attr.HostPort());
    std::string hex_string;
    StringUtil::DataToHexStr(data, length, hex_string);
    printf("result : %s.\n", hex_string.c_str());
    // compose:0001000800011f607c4f3f84
    // raw    :0001000800011f607c4f3f84
}

TEST(XorAddressMap, ComposeTest)
{

    StunXorMappedAddressAttr attr = {};
    attr.MagicCookie(0x2112a442);
    attr.AddressInfo(0x01, 28102, "124.79.99.33");
    uint8_t data[100] = {};
    int     length    = attr.ComposeAttrToBuffer(data, sizeof(data));
    printf("result length : %d.\n", length);
    printf("ip:%s,port:%d.\n", attr.HostIP().c_str(), attr.HostPort());
    std::string hex_string;
    StringUtil::DataToHexStr(data, length, hex_string);
    printf("result : %s.\n", hex_string.c_str());
    // compose:0020000800014cd45d5dc763.
    // raw    :0020000800014cd45d5dc763
}

TEST(XorAddressMap, ComposeTestV4)
{
    StunXorMappedAddressAttr attr = {};
    std::string              id   = "124add96ab65282faf39b2b9";
    std::vector<uint8_t>     d;
    StringUtil::HexStrToCharactor(id, d);
    attr.TransactionID(d.data(), d.size());
    attr.MagicCookie(0x2112a442);
    attr.AddressInfo(0x02, 45903, "240e:b8f:9153:f00:a9e3:62b7:bc1:e789");
    uint8_t data[100] = {};
    int     length    = attr.ComposeAttrToBuffer(data, sizeof(data));
    printf("result length : %d.\n", length);
    printf("ip:%s, port:%d.\n", attr.HostIP().c_str(), attr.HostPort());
    std::string hex_string;
    StringUtil::DataToHexStr(data, length, hex_string);
    printf("result:%s.\n", hex_string.c_str());
    // compose:002000140002925d051cafcd8319d29602864a98a4f85530.
    // raw    :002000140002925d051cafcd8319d29602864a98a4f85530
}

TEST(UserName, ComposeTest)
{
    StunUserNameAttr attr = {};
    attr.UserName("boar:cCnn");
    uint8_t data[100] = {};
    int     length    = attr.ComposeAttrToBuffer(data, sizeof(data));
    printf("result length:%d.\n", length);
    printf("user name:%s.\n", attr.UserName().c_str());
    std::string hex_string;
    StringUtil::DataToHexStr(data, length, hex_string);
    printf("result:%s.\n", hex_string.c_str());
    // compose:00060009626f61723a63436e6e000000.
    // raw    :00060009626f61723a63436e6e000000
}

TEST(RequestTransport, ComposeTest)
{
    StunRequestTransportAttr attr = {};
    attr.Transport(0x11);
    uint8_t data[100] = {};
    int     length    = attr.ComposeAttrToBuffer(data, sizeof(data));
    printf("result length:%d.\n", length);
    printf("value:%x.\n", attr.Transport());
    std::string hex_string;
    StringUtil::DataToHexStr(data, length, hex_string);
    printf("result:%s.\n", hex_string.c_str());
}
